﻿using System;
using GeneralDFS.BusinessLogical.FileSystemLogical;
using GeneralDFS.BusinessLogical.Nodes;
using GeneralDFS.DataEntity.Enum;
using GeneralDFS.DataEntity.IO;
using GeneralDFS.DataEntity.Nodes;

namespace GeneralDFS.BusinessLogical.IO
{
    public class FileBlock
    {
        /// <summary>
        /// 创建文件块对象，会自动分配dataNode
        /// </summary> 
        /// <returns>文件块对象</returns>
        public static FileBlockInfo CreateNewBlock()
        {
            var block = new FileBlockInfo();
            //todo 修改获取分配dataNode
            //block.DataNodeList = DataNodeCenter.Instance().GetDataNodeForBlocks();
            return block;
        }

        /// <summary>
        /// 在制定的FileBlock中检测是否有该DataNode，没有就添加进去
        /// </summary>
        /// <param name="filePath"></param>
        /// <param name="metaData"></param>
        /// <param name="dataNode"></param>
        /// <returns></returns>
        public static SearchResultState CheckFileBlockContainsDataNode(NameNode nameNode,String filePath, FileBlockMetaData metaData, DataNodeID dataNode)
        {
            var root = new Directory(nameNode.Root);
            var fileNode = root.GetNodesByPath(filePath,1)[0] as FileNodeInfo;
            var searchResult = Array.Find(fileNode.Blocks, fileblock => fileblock.Guid == metaData.Guid);
            if (searchResult == null)
            {
                var file = new File(nameNode.Config,fileNode);
                var fileBlockInfo = ConvertFromMetaData(metaData);
                file.AddBlock(fileBlockInfo);   
                searchResult = fileBlockInfo;
                LogUtil.LogInfo(String.Format("FileBlockInfo:{1} not found in File: {0}", fileNode.Name, fileBlockInfo.Guid));
            }

            var advanceSearch = Array.Find(searchResult.DataNodeList, node => node.Name == dataNode.Name);

            if (advanceSearch == null)
            {
                var newDataNodeList = new DataNodeID[searchResult.DataNodeList.Length + 1];
                searchResult.DataNodeList.CopyTo(newDataNodeList, 0);
                newDataNodeList[searchResult.DataNodeList.Length] = dataNode;
                searchResult.DataNodeList = newDataNodeList;
                searchResult = Array.Find(fileNode.Blocks, fileblock => fileblock.Guid == metaData.Guid);
                LogUtil.LogInfo(String.Format("DataNode:{0} not found in FileBlockInfo {1}", searchResult.DataNodeList[0].Name, searchResult.Guid));
                return SearchResultState.DataNodeNotFound;
            }
            return SearchResultState.DataNodeError;
        }

        public static FileBlockInfo GetFileBlock(FileSystem fileSystem,string fileNodePath, Guid guid)
        {
            FileNodeInfo fileNode = fileSystem.GetNodeByPath(fileNodePath) as FileNodeInfo;
            FileBlockInfo fileBlock = Array.Find(fileNode.Blocks, block => block.Guid == guid);
            return fileBlock;
        }

        public static FileBlockInfo ConvertFromMetaData(FileBlockMetaData metaData)
        {
            return new FileBlockInfo
                {
                    FileName = metaData.FileName,
                    FullPath = metaData.FullPath,
                    Guid = metaData.Guid,
                    Hash = metaData.Hash,
                    Length = metaData.Length,
                    Offset = metaData.Offset,
                    DataNodeList = new DataNodeID[0]
                };
        }
    }
}
